﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using ThridGroup.ERP.DTO.WarehouseManagement;
using ThridGroup.ERP.DTO.MaterielDto;
using ThridGroup.ERP.ProductionSystem;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.ObjectMapping;

namespace ThridGroup.ERP.WarehouseManagement
{
    /// <summary>
    /// 库存现有量服务实现
    /// </summary>
    public class InventoryModelServices : ApplicationService, IInventoryModelServices
    {
        private readonly IRepository<InventoryModel, int> _inventoryRepository;
        private readonly IRepository<MaterialType, int> _materialTypeRepository;
        private readonly ILogger<InventoryModelServices> _logger;

        public InventoryModelServices(
            IRepository<InventoryModel, int> inventoryRepository,
            IRepository<MaterialType, int> materialTypeRepository,
            ILogger<InventoryModelServices> logger)
        {
            _inventoryRepository = inventoryRepository;
            _materialTypeRepository = materialTypeRepository;
            _logger = logger;
        }

        /// <summary>
        /// 分页查询库存现有量
        /// </summary>
        public async Task<(List<InventoryDto> Items, int TotalCount)> GetInventoryListAsync(QueryInventoryDto query)
        {
            try
            {
                _logger.LogInformation($"开始查询库存现有量，查询条件：{System.Text.Json.JsonSerializer.Serialize(query)}");

                // 构建查询
                var queryable = await _inventoryRepository.GetQueryableAsync();
                
                // 关联物料分类表
                var materialTypeQueryable = await _materialTypeRepository.GetQueryableAsync();
                
                var joinedQuery = from inventory in queryable
                                  join materialType in materialTypeQueryable on inventory.MaterialTypeId equals materialType.Id into materialGroup
                                  from material in materialGroup.DefaultIfEmpty()
                                  where !inventory.IsDeleted
                                  select new { Inventory = inventory, MaterialType = material };

                // 应用筛选条件
                if (!string.IsNullOrWhiteSpace(query.ProductMaterielCode))
                {
                    joinedQuery = joinedQuery.Where(x => x.Inventory.ProductMaterielCode.Contains(query.ProductMaterielCode));
                }

                if (!string.IsNullOrWhiteSpace(query.ProductMaterielName))
                {
                    joinedQuery = joinedQuery.Where(x => x.Inventory.ProductMaterielName.Contains(query.ProductMaterielName));
                }

                if (!string.IsNullOrWhiteSpace(query.WarehouseName))
                {
                    joinedQuery = joinedQuery.Where(x => x.Inventory.WarehouseName.Contains(query.WarehouseName));
                }

                if (!string.IsNullOrWhiteSpace(query.SupplierName))
                {
                    joinedQuery = joinedQuery.Where(x => x.Inventory.SupplierName.Contains(query.SupplierName));
                }

                if (query.MaterialTypeId.HasValue && query.MaterialTypeId.Value > 0)
                {
                    joinedQuery = joinedQuery.Where(x => x.Inventory.MaterialTypeId == query.MaterialTypeId.Value);
                }

                if (query.InventoryValidity.HasValue)
                {
                    joinedQuery = joinedQuery.Where(x => x.Inventory.InventoryValidity == query.InventoryValidity.Value);
                }

                // 获取总数
                var totalCount = joinedQuery.Count();

                // 分页和排序
                var items = joinedQuery
                    .OrderByDescending(x => x.Inventory.CreateTime)
                    .Skip((query.Page - 1) * query.Limit)
                    .Take(query.Limit)
                    .ToList();

                // 转换为DTO
                var result = items.Select(x =>
                {
                    var dto = ObjectMapper.Map<InventoryModel, InventoryDto>(x.Inventory);
                    dto.MaterialTypeName = x.MaterialType?.MaterialTypeName ?? "未分类";
                    return dto;
                }).ToList();

                _logger.LogInformation($"库存查询完成，共{totalCount}条记录，当前页{result.Count}条");

                return (result, totalCount);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"查询库存现有量失败：{System.Text.Json.JsonSerializer.Serialize(query)}");
                throw;
            }
        }

        /// <summary>
        /// 根据ID获取库存信息
        /// </summary>
        public async Task<InventoryDto> GetInventoryByIdAsync(int id)
        {
            try
            {
                _logger.LogInformation($"开始获取库存信息，ID：{id}");

                if (id <= 0)
                {
                    throw new ArgumentException("无效的ID");
                }

                var inventory = await _inventoryRepository.GetAsync(id);
                if (inventory == null)
                {
                    throw new Exception($"未找到ID为{id}的库存记录");
                }

                var dto = ObjectMapper.Map<InventoryModel, InventoryDto>(inventory);

                // 获取物料分类名称
                if (inventory.MaterialTypeId > 0)
                {
                    var materialType = await _materialTypeRepository.FirstOrDefaultAsync(x => x.Id == inventory.MaterialTypeId);
                    dto.MaterialTypeName = materialType?.MaterialTypeName ?? "未分类";
                }

                _logger.LogInformation($"成功获取库存信息，ID：{id}");
                return dto;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"获取库存信息失败，ID：{id}");
                throw;
            }
        }

        /// <summary>
        /// 获取物料分类树形结构
        /// </summary>
        public async Task<List<MaterielTypeTreeSelectDto>> GetMaterialTypeTreeAsync()
        {
            try
            {
                _logger.LogInformation("开始获取物料分类树形结构");

                var allTypes = await _materialTypeRepository.GetListAsync(x => !x.IsDeleted && x.IsEnable);
                var orderedTypes = allTypes.OrderBy(x => x.Index).ToList();

                // 获取根节点
                var rootTypes = orderedTypes.Where(x => x.ParentId == 0).ToList();
                var result = new List<MaterielTypeTreeSelectDto>();

                foreach (var rootType in rootTypes)
                {
                    var rootDto = new MaterielTypeTreeSelectDto
                    {
                        Id = rootType.Id,
                        Label = rootType.MaterialTypeName,
                        Children = new List<MaterielTypeTreeSelectDto>()
                    };

                    // 递归构建子节点
                    BuildMaterialTypeTree(orderedTypes, rootDto);
                    result.Add(rootDto);
                }

                _logger.LogInformation($"成功获取物料分类树形结构，共{result.Count}个根节点");
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取物料分类树形结构失败");
                throw;
            }
        }

        /// <summary>
        /// 递归构建物料分类树
        /// </summary>
        private void BuildMaterialTypeTree(List<MaterialType> allTypes, MaterielTypeTreeSelectDto parent)
        {
            var children = allTypes
                .Where(x => x.ParentId == parent.Id)
                .OrderBy(x => x.Index)
                .ToList();

            foreach (var child in children)
            {
                var childDto = new MaterielTypeTreeSelectDto
                {
                    Id = child.Id,
                    Label = child.MaterialTypeName,
                    Children = new List<MaterielTypeTreeSelectDto>()
                };

                BuildMaterialTypeTree(allTypes, childDto);
                parent.Children.Add(childDto);
            }
        }
    }
}
